﻿
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using OpenIddict.Client;
using SageKing.Core.Extensions;
using SageKing.Core.Options;

namespace SageKing.OpenIddict.Client.Features;

public class OpenIddictClientFeature : FeatureBase
{
    public OpenIddictClientFeature(IModule module) : base(module)
    {
    }

    public OpenIdClientOptions OpenIdOptions { get; set; }

    /// <inheritdoc />
    public override void Apply(IConfigurationManager configurationManager, IHostEnvironment hostEnvironment)
    {
        ArgumentNullException.ThrowIfNull(configurationManager);
        if (OpenIdOptions == null)
        {
            OpenIdOptions = new OpenIdClientOptions();
            configurationManager.Bind(OpenIdOptions, OpenIdOptions.SectionName);
        }

        Services.AddSingleton(OpenIdOptions);

        Services.AddHttpClient(HttpClientConsts.HttpClientIssuerKey, client =>
        {
            client.BaseAddress = new Uri(OpenIdOptions.Issuer);
            client.DefaultRequestHeaders.Add("User-Issuer", OpenIdOptions.Issuer);
        });

        Services.AddOpenIddict()
           .AddClient(options =>
           {
               // Allow grant_type=client_credentials to be negotiated.
               options.AllowClientCredentialsFlow();

               // Disable token storage, which is not necessary for non-interactive flows like
               // grant_type=password, grant_type=client_credentials or grant_type=refresh_token.
               options.DisableTokenStorage();

               // Register the System.Net.Http integration and use the identity of the current
               // assembly as a more specific user agent, which can be useful when dealing with
               // providers that use the user agent as a way to throttle requests (e.g Reddit).
               options.UseSystemNetHttp()
                      .SetProductInformation(Module.CallAssembly);

               // Add a client registration matching the client application definition in the server project.
               options.AddRegistration(new OpenIddictClientRegistration
               {
                   Issuer = new Uri(OpenIdOptions.Issuer, UriKind.Absolute),

                   ClientId = OpenIdOptions.ClientId,
                   ClientSecret = OpenIdOptions.ClientSecret
               });
           });

        Services.AddScoped<IOpenIddictToken, OpenIddictClientToken>();

    }
}
